from django.db import models
from datetime import datetime, date, timedelta

class TASK_STATUS:
    CHOICES = ( 
            ("ready", "Ready"), 
            ("running","Running..."), 
    )
    READY   = CHOICES[0][0]
    RUNNING = CHOICES[1][0]

class Task(models.Model):
    name             = models.CharField(maxlength=255)
    script           = models.TextField(default="result=0")
    interval_days    = models.PositiveIntegerField()
    interval_hours   = models.PositiveIntegerField()
    interval_minutes = models.PositiveIntegerField()
    next_execution   = models.DateTimeField()
    last_execution   = models.DateTimeField()
    status           = models.CharField(maxlength=50, choices=TASK_STATUS.CHOICES, default=TASK_STATUS.READY )
    last_result      = models.CharField(maxlength=255)
    enabled          = models.BooleanField()
    
    def __str__(self):
        return self.name
    
    class Admin:
        list_display=('name','interval_days','interval_hours','interval_minutes','next_execution','last_execution','status','last_result')
        list_filter=('status','enabled')
    
    def __run__(self):
        msg, result = "Script not found", 404
        
        self.status = TASK_STATUS.RUNNING
        self.save()
        try:
            sc = self.script.replace('\r\n','\n')
            exec(sc)
            msg = "OK"
        except Exception, e:
            result=500
            msg = e
        self.last_result = result
        self.status = TASK_STATUS.READY
        from datetime import datetime, timedelta
        self.last_execution = datetime.now()
        self.next_execution = self.last_execution + timedelta(days=self.interval_days, hours=self.interval_hours, minutes=self.interval_minutes)
        self.save()
        return msg, result
    
    def run(self):
        if not self.enabled:
            return "Task not enabled"
        if self.next_execution >= datetime.now():
            return "Task not in time to be launched"
        if self.status != TASK_STATUS.RUNNING: 
            msg, res = self.__run__()
            if res > 0:
                return 'Task execution ERROR. Task -%s-, error code=%d, error msg=%s' % (self.name, res, msg)
            return "Task executed, result: %s" % str(res)
        return "Task already running"

    @classmethod
    def run_all(cls):
        report = ["Checking tasks..."]
        ts = Task.objects.filter(enabled=True)
        for t in ts:
            report.append("Task %s: %s" % (t.name, t.run() ))
        
        return "\n".join(report)
